﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Web.Mvc;
using System.Web.Security;
using Beeldbankmvc.Code;
using Beeldbankmvc.Models;
using Beeldbankmvc.ViewModels;

namespace Beeldbankmvc.Controllers
{
    [HandleErrorWithELMAH]
    public class ReactionController : Controller
    {
        ReactionRepository reactionRepository = new ReactionRepository();
        ReactionCorrespondenceRepository reactionCorrespondenceRepository = new ReactionCorrespondenceRepository();
        ReactionStatusRepository reactionStatusRepository = new ReactionStatusRepository();
        MediaObjectRepository mediaObjectRepository = new MediaObjectRepository();
        
        //
        // GET: /Reaction/
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Index(int? reactionPageIndex)
        {
            ReactionRepository reactionRepository = new ReactionRepository();            

            ReactionViewModel rvModel = new ReactionViewModel();
            rvModel.pageSize = Constants.PAGE_SIZE;
            rvModel.reactionPageIndex = 0;

            if (reactionPageIndex.HasValue)
                rvModel.reactionPageIndex = reactionPageIndex.Value;

            string identityName = "";
            if (!string.IsNullOrWhiteSpace(this.HttpContext.User.Identity.Name))
                identityName = this.HttpContext.User.Identity.Name;

            if (Request.QueryString["sort"] != null)
            {
                if (Request.QueryString["sort"].Equals("datum"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 0, false).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, false);
                }
                if (Request.QueryString["sort"].Equals("status"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 1, false).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, false);
                }
                if (Request.QueryString["sort"].Equals("onderwerp"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 2, false).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, false);
                }
                if (Request.QueryString["sort"].Equals("categorie"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 3, false).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, false);
                }
                if (Request.QueryString["sort"].Equals("mediaObject"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 4, false).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRowsOnlyMediaObject(identityName, false);
                }
            }
            else
            {
                rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 4, false).ToList();
                rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRowsOnlyMediaObject(identityName, false);
            }

            return View(rvModel);
        }

        //
        // GET: /Reaction/
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult IndexClosed(int? reactionPageIndex)
        {
            ReactionRepository reactionRepository = new ReactionRepository();

            ReactionViewModel rvModel = new ReactionViewModel();
            rvModel.pageSize = Constants.PAGE_SIZE;
            rvModel.reactionPageIndex = 0;

            if (reactionPageIndex.HasValue)
                rvModel.reactionPageIndex = reactionPageIndex.Value;

            string identityName = "";
            if (!string.IsNullOrWhiteSpace(this.HttpContext.User.Identity.Name))
                identityName = this.HttpContext.User.Identity.Name;

            if (Request.QueryString["sort"] != null)
            {
                if (Request.QueryString["sort"].Equals("datum"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 0, true).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, true);
                }
                if (Request.QueryString["sort"].Equals("status"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 1, true).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, true);
                }
                if (Request.QueryString["sort"].Equals("onderwerp"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 2, true).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, true);
                }
                if (Request.QueryString["sort"].Equals("categorie"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 3, true).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRows(identityName, true);
                }
                if (Request.QueryString["sort"].Equals("mediaObject"))
                {
                    rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 4, true).ToList();
                    rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRowsOnlyMediaObject(identityName, true);
                }
            }
            else
            {
                rvModel.reactionObjects = reactionRepository.FindAllSorted(rvModel.pageSize, rvModel.reactionPageIndex, identityName, 4, true).ToList();
                rvModel.numberOfRowsReaction = reactionRepository.getNumberOfReactionRowsOnlyMediaObject(identityName, true);
            }

            return View(rvModel);
        }

        //
        // GET: /Reaction/Details/5
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Details(int id)
        {
            return View();
        }

        //
        // GET: /Reaction/Create   
        public ActionResult Create()
        {
            ReactionModel model = new ReactionModel();
            
            ViewData["ReactionSubjectList"] = ReactionModel.reactionSubjectList();
            ViewData["ReactionCategoryList"] = ReactionModel.categoryList();

            string userName = User.Identity.Name;
            MembershipUser currentUser = Membership.GetUser(userName);
            if (currentUser != null)
            {
                // Fetch additional information from user repository
                UserRepository userRepository = new UserRepository();
                EditAccountModel accountmodel = userRepository.FindOne(new Guid(currentUser.ProviderUserKey.ToString()));

                model.Email = accountmodel.Email;
                model.Name = accountmodel.FirstName + " " + accountmodel.Prepositions + " " + accountmodel.LastName;
                model.Telephone = accountmodel.Phone;
            }

            return View(model);
        } 

        //
        // POST: /Reaction/Create
        [HttpPost]
        public ActionResult Create(FormCollection collection, ReactionModel model)
        {
            try
            {
                if ((model.Message.Trim() != "") && (model.Name.Trim() != "") && (model.Email.Trim() != ""))
                {
                    model.MediaObjectOmschrijving = "nvt";

                    model.Subject = collection["Subject"].ToString();
                    model.Category = collection["Category"].ToString();

                    // save the working version 
                    reactionRepository.AddFirst(model);
                    reactionRepository.Save();

                    ReactionCorrespondenceModel correspondenceModel = new ReactionCorrespondenceModel();

                    // Send notification to admin regarding this newly created reaction
                    Code.Notification.newReactionCreated(model.Email, model.Name, IdMapper.mapReactionSubject(model.Subject), IdMapper.mapReactionCategory(model.Category), model.Message);

                    // Send a fake auto reply message form the admin computer to the user
                    Code.Notification.autoRespondReactionCreated(model.Email, model.Name, IdMapper.mapReactionSubject(model.Subject), IdMapper.mapReactionCategory(model.Category), model.Message);

                    // Send a backup of the submited data to the user
                    Code.Notification.backupReactionCreated(model.Email, model.Name, IdMapper.mapReactionSubject(model.Subject), IdMapper.mapReactionCategory(model.Category), model.Message);

                    return RedirectToAction("ThankYou");
                }
                else
                {
                    ViewData["ReactionSubjectList"] = ReactionModel.reactionSubjectList();
                    ViewData["ReactionCategoryList"] = ReactionModel.categoryList();

                    ViewData["Email"] = model.Email;
                    ViewData["Name"] = model.Name;
                    ViewData["Phone"] = model.Telephone;
                    
                    return View(model);
                }
            }
            catch
            {
                ViewData["ReactionSubjectList"] = ReactionModel.reactionSubjectList();
                ViewData["ReactionCategoryList"] = ReactionModel.categoryList();

                return View(model);
            }
        }
        
        //
        // GET: /Reaction/Edit/5
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Edit(int id)
        {
            ReactionRepository reactionRepository = new ReactionRepository();
            
            ViewData["SubjectList"] = ReactionModel.subjectList();
            ViewData["CategoryList"] = ReactionModel.categoryList();

            BEELDBANK_REACTIE currentReaction = reactionRepository.FindOne(id);
            ReactionViewModel rvModel = new ReactionViewModel(currentReaction); 

            List<BEELDBANK_REACTIE> reactionList = new List<BEELDBANK_REACTIE>();
            reactionList.Add(currentReaction);
            rvModel.reactionObjects = reactionList;

            return View(rvModel);
        }

        //
        // POST: /Reaction/Edit/5
        [HttpPost]
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Edit(int id, FormCollection collection)
        {
            var currentReaction = reactionRepository.FindOne(id);
            ReactionViewModel model = new ReactionViewModel(currentReaction);

            try
            {
                // Save a copy of the edited service call to the correspondence tabel
                BEELDBANK_REACTIE_CORRESPONDENTIE correspondence = new BEELDBANK_REACTIE_CORRESPONDENTIE();
                correspondence.ReactieId = id;
                correspondence.Datum = DateTime.Now;
                correspondence.Status = int.Parse(Request.Form["ReactionStatuses"]);
                correspondence.Boodschap = collection["reactionObjects[0].Boodschap"].ToString();
                correspondence.Subject = collection["Subject"].ToString();
                correspondence.Category = collection["Category"].ToString();
                reactionCorrespondenceRepository.Add(correspondence);
                reactionCorrespondenceRepository.Save();
                
                // save the edited service call to the database
                currentReaction.Id = id;
                currentReaction.Telefoon = collection["reactionObjects[0].Telefoon"].ToString();
                currentReaction.Status = int.Parse(Request.Form["ReactionStatuses"]);
                currentReaction.Boodschap = collection["reactionObjects[0].Boodschap"].ToString();
                currentReaction.Subject = collection["Subject"].ToString();
                currentReaction.Category = collection["Category"].ToString();

                // if the last status was reached set de 'DatumGesloten' field
                if (int.Parse(Request.Form["ReactionStatuses"]) == reactionStatusRepository.CountStatuses())
                    currentReaction.DatumGesloten = DateTime.Now;

                reactionRepository.Update(currentReaction);

                // Todo: hier een juiste mail van maken en eventueel meerdere zoals bij create
                //
                if (collection["submit"].ToLower().Equals("opslaan en reactie sturen") && int.Parse(Request.Form["ReactionStatuses"]) != reactionStatusRepository.CountStatuses())
                {
                    MailAddress to = new MailAddress(currentReaction.EmailAdres,currentReaction.Naam);
                    Notification.reactionResponse(to, Encrypt.psEncrypt(id.ToString()));
                }

                if (User.IsInRole("Administrator"))
                    return RedirectToAction("Index", new { sort = "datum" });
                else
                    return RedirectToAction("Index", new { sort = "mediaObject" });
            }
            catch
            {
                ViewData["SubjectList"] = ReactionModel.subjectList();
                ViewData["CategoryList"] = ReactionModel.categoryList();

                return View(model);
            }
        }

        //
        // GET: /Reaction/EditVisitor/5
        public ActionResult EditVisitor(string id)
        {
            int decryptedId = Convert.ToInt32(Encrypt.psDecrypt(id));

            ReactionRepository reactionRepository = new ReactionRepository();

            ViewData["SubjectList"] = ReactionModel.subjectList();
            ViewData["CategoryList"] = ReactionModel.categoryList();

            BEELDBANK_REACTIE currentReaction = reactionRepository.FindOne(decryptedId);
            ReactionViewModel rvModel = new ReactionViewModel(currentReaction);

            List<BEELDBANK_REACTIE> reactionList = new List<BEELDBANK_REACTIE>();
            reactionList.Add(currentReaction);
            rvModel.reactionObjects = reactionList;

            return View(rvModel);
        }

        //
        // POST: /Reaction/EditVisitor/5
        [HttpPost]
        public ActionResult EditVisitor(string id, FormCollection collection)
        {
            int decryptedId = Convert.ToInt32(Encrypt.psDecrypt(id));

            var currentReaction = reactionRepository.FindOne(decryptedId);
            ReactionViewModel model = new ReactionViewModel(currentReaction);

            try
            {
                // Save a copy of the edited service call to the correspondence tabel
                BEELDBANK_REACTIE_CORRESPONDENTIE correspondence = new BEELDBANK_REACTIE_CORRESPONDENTIE();
                correspondence.ReactieId = decryptedId;
                correspondence.Datum = DateTime.Now;
                correspondence.Boodschap = collection["reactionObjects[0].Boodschap"].ToString();
                correspondence.IsVisitorResponse = true;
                reactionCorrespondenceRepository.Add(correspondence);
                reactionCorrespondenceRepository.Save();

                // save the edited service call to the database
                currentReaction.Id = decryptedId;
                currentReaction.Boodschap = collection["reactionObjects[0].Boodschap"].ToString();
                reactionRepository.Update(currentReaction);

                // Send notification to admin regarding this newly created reaction
                Code.Notification.newReactionCreated(currentReaction.EmailAdres, currentReaction.Naam, IdMapper.mapReactionSubject(currentReaction.Subject), IdMapper.mapReactionCategory(currentReaction.Category), currentReaction.Boodschap);

                // Send a fake auto reply message form the admin computer to the user
                Code.Notification.autoRespondReactionCreated(currentReaction.EmailAdres, currentReaction.Naam, IdMapper.mapReactionSubject(currentReaction.Subject), IdMapper.mapReactionCategory(currentReaction.Category), currentReaction.Boodschap);

                // Send a backup of the submited data to the user
                Code.Notification.backupReactionCreated(currentReaction.EmailAdres, currentReaction.Naam, IdMapper.mapReactionSubject(currentReaction.Subject), IdMapper.mapReactionCategory(currentReaction.Category), currentReaction.Boodschap);

                return RedirectToAction("ThankYou");
            }
            catch
            {
                ViewData["SubjectList"] = ReactionModel.subjectList();
                ViewData["CategoryList"] = ReactionModel.categoryList();

                return View(model);
            }
        }

        // TODO: check if this beheerder is the owner
        // GET: /Reaction/Delete/5
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Delete(int id)
        {
            BEELDBANK_REACTIE reaction = reactionRepository.FindOne(id);

            try
            {
                // Delete the reaction
                reactionRepository.Delete(reaction);
                reactionRepository.Save();
            }
            catch
            {
            }

            if (reaction.Subject == "6")
                return RedirectToAction("Details", "MediaObject", new { id = reaction.MediaObjectId });
            else
                if (User.IsInRole("Administrator"))
                    return RedirectToAction("Index", new { sort = "datum" });
                else
                    return RedirectToAction("Index", new { sort = "mediaObject" });
        }

        // TODO: check if this beheerder is the owner
        // GET: /Reaction/Delete/5
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Approve(int id)
        {
            BEELDBANK_REACTIE reaction = reactionRepository.FindOne(id);

            try
            {
                BEELDBANK_MEDIAOBJECT mediaObject = null;
                
                mediaObject = mediaObjectRepository.FindOne(reaction.MediaObjectId.Value);
                mediaObject.AltTekst = reaction.MediaObjectTitel;
                mediaObject.Omschrijving = reaction.MediaObjectOmschrijving;
                mediaObject.Lokatie = reaction.MediaObjectLokatie;
                mediaObject.StatusId = Constants.ITEM_STATUS_EDIT_UNKNOWN;
                // check which keywords are in the summery and add them to the keywords collection
                mediaObjectRepository.CalculateKeywords(reaction.MediaObjectId.Value);

                mediaObjectRepository.Save();
            }
            catch
            {
            }

            return RedirectToAction("Details", "MediaObject", new { id = reaction.MediaObjectId });
        }

        // TODO: check if this beheerder is the owner
        // GET: /Reaction/Delete/5
        [Authorize(Roles = "Administrator,Eindredacteur,Beheerder")]
        public ActionResult Finalize(int id)
        {
            try
            {
                BEELDBANK_MEDIAOBJECT mediaObject = null;

                mediaObject = mediaObjectRepository.FindOne(id);
                mediaObject.StatusId = Constants.ITEM_STATUS_EXTERN;

                mediaObjectRepository.Save();
            }
            catch
            {
            }

            return RedirectToAction("Details", "MediaObject", new { id = id });
        }

        //
        // GET: /Reaction/ThankYou
        public ActionResult ThankYou()
        {
            return View();
        }

    }
}
